home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 2
/
AACD 2.iso
/
AACD
/
Magazine
/
GraphicsCards
/
Warp3D
/
Developer
/
Source
/
WarpTest.c
Wrap
C/C++ Source or Header
|
1999-02-04
|
47KB
|
1,596 lines
/*
WarpTest
This program is part of the Warp3D project.
Copyright © 1998 Thomas Frieden, Hans-Jörg Frieden, Sam Jordan
You may freely modify and/or use any part of this file. It
is considered an example for programming Warp3D.
This is a small program that shows some effects that can be done
with Warp3D, and may also serve as an example for programming
with Warp3D. It demonstrates fog, alpha blending, texture mapping,
both linear and perspective corrected, gouraud shading, filtering,
light mapping, mipmapping, including automatic mipmap generation,
and double buffering. Here`s how to use it:
From shell, enter WarpTest <texture.ppm>. If the texture is omitted,
wall.ppm is taken as default.
The wall can be moved and rotated with the cursor keys. Pressing the
mouse button and moving the mouse also rotates the wall. You can also
use the following keys for switching different effects:
f - Toggle fogging.
8 - Push back the fog end value (observe the second last text row)
5 - Push fog end towards viewer
9 - Push back fog start
6 - Push fog start towards viewer
t - toggle texture mapping/gouraud shading
e - toggle light mapping
p - toggle linear/perspective corrected mapping
l - turn on alpha blending
1 - set filtering to W3D_NEAREST (no texture filtering)
2 - set filtering to W3D_LINEAR (bilinear texture
3 - set filtering to W3D_NEAREST_MIP_NEAREST (mipmapping, no filtering)
4 - set filtering to W3D_LINEAR_MIP_LINEAR (trilinear filtering with
mipmapping)
a - show mipmaps (don`t mind the flickering, they are only drawn
to the first buffer)
b - show vertex coordinates (not very useful)
c - slow motion
d - draw the background pattern
Pressing 'a' shows the current texture, along with the mipmaps
that were automatically created. These mipmaps are created with
a simple median where four pixels are summed up and divided by
four to produce a new pixel.
History
-------
6-Aug-98 First public developer release
8-Aug-98 Added a background patter switch (red lines), plus a
key ('d') to toggle it. Additionally, Opacity for
textures was replaced with a gradient pattern running
from top-left to bottom-right.
13-Sep-98 ZBuffering now works
28-Sep-98 Pressing F not switches hinting about fogging (press twice,
I wa too lazy to correct the bug :)
3-Oct-98 Added TEXTURE and ZBUFFER command line switches
12-Jan-99 Added Outline mode with W3D_DrawLineLoop
Added V2 driver interface
Increased library minimum version to 2.0
Added information printing about drivers
Added example for W3D_QueryDriver
*/
//+ Includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/asl.h>
#ifndef __PPC__
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/cybergraphics.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#else
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/cybergraphics_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/powerpc_protos.h>
#endif
#ifndef __STORM__
#include <cybergraphx/cybergraphics.h>
#else
#include <cybergraphics/cybergraphics.h>
#endif
#include <Warp3D/Warp3D.h>
#include <clib/Warp3D_protos.h>
#ifndef __PPC__
#ifndef __STORM__
#include <pragmas/Warp3D_pragmas.h>
#else
#include <pragma/Warp3D_lib.h>
#endif
#endif
//-
//+ Stuff
#ifdef __STORM__
char version[] = "$VER: WarpTest_StormC 1.1 (6-Aug-98)";
#else
char version[] = "$VER: WarpTest_SAS/C 1.1 (6-Aug-98)";
#endif
#ifndef __STORM__
#pragma msg 193 ignore
#pragma msg 93 ignore
#endif
#ifndef __PPC__
struct Library *Warp3DBase;
#else
struct Library *Warp3DPPCBase;
#endif
struct Library *CyberGfxBase;
struct Screen *screen;
struct Window *window;
int bufnum = 0;
BOOL outline = FALSE;
BOOL zb = FALSE;
struct RDArgs *rda = NULL;
#define TEMPLATE "TEXTURE,ZBUFFER/S,REPEAT/N,LIGHTMAP/K"
ULONG texturesize;
UBYTE *texture;
UBYTE *lightmap;
LONG result[10];
W3D_Texture *tex, *lighttex = NULL;
W3D_Triangle tri;
W3D_Color ccol = {0.0, 1.0, 0.0, 0.8};
W3D_Double zdepth = 0.8;
ULONG zmode = 0;
ULONG DLevel=0, DWrap=0;
int persp = 0;
int forcelin = 0;
float divisor = 2048.0;
float factor = 16.f;
float tmax = 256.f;
float lastw = 0.f;
float lastd = 0.f;
ULONG CurrentBlend = 0;
ULONG BlendModes[] = {W3D_REPLACE, W3D_DECAL, W3D_MODULATE, W3D_BLEND};
ULONG CurrentFog = 0;
ULONG FogModes[] = {0, W3D_FOG_LINEAR, W3D_FOG_EXP, W3D_FOG_EXP_2, W3D_FOG_INTERPOLATED};
W3D_Double LastZ = 0.0;
int curfilt = 1;
int drag = 0;
int push = 0;
int second_wall = 0;
const float Back = 40.0;
const float Front = 0.5;
#define kzen (-65535.0*(Back*Front)/(Back-Front))
#define z0 ( 65535.0*Back/(Back-Front))
#define SCALE 240
typedef struct {
float x,y,z;
float u,v;
float iz;
} Vector3;
typedef struct {
float m11, m12, m13;
float m21, m22, m23;
float m31, m32, m33;
} Matrix3;
Vector3 Square[4] = {
// x y z u v
{-1.f, 1.f, 0.f, 0.f, 0.f},
{ 1.f, 1.f, 0.f, 1.f, 0.f},
{ 1.f, -1.f, 0.f, 1.f, 1.f},
{-1.f, -1.f, 0.f, 0.f, 1.f}
};
Vector3 LSquare[4] = {
// x y z u v
{-1.f, 1.f, 0.f, 0.f, 0.f},
{ 1.f, 1.f, 0.f, 1.f, 0.f},
{ 1.f, -1.f, 0.f, 1.f, 1.f},
{-1.f, -1.f, 0.f, 0.f, 1.f}
};
Vector3 TempSquare[4];
Vector3 Pos = {0.f, 0.f, 3.f, 0.f, 0.f}; // Position of wall
float theta = 0.0; // Wall Angle
int aflag=0, bflag=0, cflag=0, dflag=0;
ULONG FogQuality = W3D_H_NICE;
W3D_Fog myFog = {
1.0,0.2,1.0,
{8.1/32.0, 8.1/32.0, 17.1/32.0}
};
void *texmap;
//-
//+ Matrix/Vector stuff
void MatVec(Matrix3 *M, Vector3 *v, Vector3 *r)
{
// Calcuate r=Mv
r->x = M->m11*v->x + M->m12*v->y + M->m13*v->z;
r->y = M->m21*v->x + M->m22*v->y + M->m23*v->z;
r->z = M->m31*v->x + M->m32*v->y + M->m33*v->z;
}
void RotYMat(Matrix3 *M, float theta)
// Create a Y axis rotation matrix by angle theta (theta in degrees)
{
theta = theta/180.f * PI;
M->m11 = (float)cos(theta);
M->m13 = -(float)sin(theta);
M->m31 = (float)sin(theta);
M->m33 = (float)cos(theta);
M->m22 = 1.f;
M->m12 =
M->m21 =
M->m23 =
M->m32 = 0.f;
}
void Project(Vector3 *v)
{
if (v->z == 0.f) v->z+=0.0001;
v->iz = 1.0/v->z;
v->x = 320+SCALE*v->x*(v->iz);
v->y = 240-SCALE*v->y*(v->iz);
v->z = ((kzen/v->z)+z0)/65536.f;
}
void VecAdd(Vector3 *a, Vector3 *b, Vector3 *r)
// Calcuate r=a+b;
// I love C++!!!
{
r->x = a->x + b->x;
r->y = a->y + b->y;
r->z = a->z + b->z;
}
void Transform(Vector3 Pos, float theta)
// Transform the wall to the desired orientation
{
Matrix3 M;
Vector3 r;
int i;
RotYMat(&M, theta); // Create rotation matrix;
for (i=0; i<4; i++) {
MatVec(&M, &Square[i], &TempSquare[i]);
VecAdd(&TempSquare[i], &Pos, &TempSquare[i]);
//}
//for (i=0; i<4; i++) {
Project(&TempSquare[i]);
}
}
//-
//+ "LoadTextureFromPPM"
#define ARGB8888toARGB1555(ic) (0x8000 | ((ic&0xF8)>>3) | ((ic&0xF800)>>6) | ((ic&0xF80000)>>9))
#define ARGB8888toARGB4444(ic) ((ic&0xF0000000)>>16 | \
(ic&0x00F00000)>>12 | \
(ic&0x0000F000)>>8 | \
(ic&0x000000F0)>>4)
UBYTE *LoadTextureFromPPM(APTR where, char *filename, UBYTE Opacity, int *w, int *h)
{
ULONG *map, *map2;
FILE *f;
int i,j;
UBYTE r,g,b;
UWORD a;
unsigned long x,y;
int opqy, opqx, o;
f=fopen(filename, "r");
if (!f) {
printf("Error: Unable to open file '%s'\n", filename);
return NULL;
}
#ifndef __STORM__
i=fscanf(f, "P6\n%ld %ld\n255\n", &x, &y);
#else
i=fscanf(f, "P6\n%ld\n%ld\n255\n", &x, &y);
#endif
if (i!=2) {
printf("Error: This seems to be no PPM file\n");
fclose(f);
return NULL;
}
*w = x;
*h = y;
if (where==NULL) {
map2 = map = AllocVec(x*y*4, MEMF_PUBLIC);
} else {
map = map2 = where;
}
if (!map) {
fclose(f);
printf("Error: Out of memory\n");
return NULL;
}
opqy = 256/y;
opqx = 256/x;
opqx = opqx>>1;
o=0;
for (i=0; i<y; i++) {
for(j=0; j<x; j++) {
if (o+j*opqy > 255)
Opacity = 255;
else
Opacity = (UBYTE)(o+j*opqy);
r=(UBYTE)fgetc(f);
g=(UBYTE)fgetc(f);
b=(UBYTE)fgetc(f);
*map = (Opacity<<24) | ((r&0xFF)<<16) | ((g&0xFF)<<8) | (b&0xFF);
// *map = (Opacity<<8) | ((r&0xFF)) | ((g&0xFF)<<24) | (b&0xFF)<<16;
map++;
}
o += opqx;
}
fclose(f);
return (UBYTE *)map2;
}
//-
//+ GenTexture
int log2(int x)
{
// Kludgy but fast :)
// floats are too small for log(x)/log(2)...
switch(x) {
case 65536: return 16;
case 32768: return 15;
case 16384: return 14;
case 8192: return 13;
case 4096: return 12;
case 2048: return 11;
case 1024: return 10;
case 512: return 9;
case 256: return 8;
case 128: return 7;
case 64: return 6;
case 32: return 5;
case 16: return 4;
case 8: return 3;
case 4: return 2;
case 2: return 1;
case 1: return 0;
}
}
BOOL GenTexture(W3D_Context* context, char* name, LONG repeat)
{
UBYTE *where;
int w, h;
ULONG error;
int maps,i;
// This loads a ppm (24 bit) texture file from disk, and sets
// it to 50% transparency (0x7F)...
where = LoadTextureFromPPM(NULL, name, 0x7F, &w, &h);
if (!where) return FALSE;
printf("Size: %ld×%ld\n", w,h);
// This sets the square's texture coordinates to the right pixel values
for (i=0;i<4; i++) {
Square[i].u *= (w-1); // -1
Square[i].v *= (h-1); // -1
if (repeat > 1) {
Square[i].u *= repeat;
Square[i].v *= repeat;
}
}
texmap = where;
tex = W3D_AllocTexObjTags(context, &error,
W3D_ATO_IMAGE, where, // The image data
W3D_ATO_FORMAT, W3D_A8R8G8B8, // This is a 32 bit image
W3D_ATO_WIDTH, w, // Length of one side
W3D_ATO_HEIGHT, h,
W3D_ATO_MIPMAP, 0xffff, // Mipmap mask - see autodocs
TAG_DONE);
if (!tex || error != W3D_SUCCESS) {
printf("Error generating texture: ");
switch(error) {
case W3D_ILLEGALINPUT:
printf("Illegal input\n");
break;
case W3D_NOMEMORY:
printf("Out of memory\n");
break;
case W3D_UNSUPPORTEDTEXSIZE:
printf("Unsupported texture size\n");
break;
case W3D_NOPALETTE:
printf("Chunky texture without palette specified\n");
break;
case W3D_UNSUPPORTEDTEXFMT:
printf("Texture format not supported\n");
break;
default:
printf("ahem... An error has occured\n");
}
return FALSE;
}
return TRUE;
}
//-
//+ GenLightmap
// Ok, this is a cheap, but who cares :)
// In a real application, you would have this code only once
BOOL GenLightmap(W3D_Context* context, char* name, LONG repeat)
{
#define LEVEL a
UBYTE *where, *here;
int w, h;
ULONG error;
int maps,i;
int a;
// This loads a ppm (24 bit) texture file from disk, and sets
// it to 50% transparency (0x7F)...
where = LoadTextureFromPPM(NULL, name, 0x7F, &w, &h);
if (!where) return FALSE;
printf("Size: %ld×%ld\n", w,h);
// Convert it to pure alpha
// Should really use a W3D_A8 here, but I'm too lazy
here = where;
for (i = 0; i < w*h; i++) {
a = (here[1] + here[2] + here[3])/3;
here[0] = a;
here[1] = LEVEL;
here[2] = LEVEL;
here[3] = LEVEL;
here += 4;
}
// This sets the square's texture coordinates to the right pixel values
for (i=0;i<4; i++) {
LSquare[i].u *= (w-1); // -1
LSquare[i].v *= (h-1); // -1
if (repeat > 1) {
LSquare[i].u *= repeat;
LSquare[i].v *= repeat;
}
}
lightmap = where;
lighttex = W3D_AllocTexObjTags(context, &error,
W3D_ATO_IMAGE, where, // The image data
W3D_ATO_FORMAT, W3D_A8R8G8B8, // This is a 32 bit image
W3D_ATO_WIDTH, w, // Length of one side
W3D_ATO_HEIGHT, h,
W3D_ATO_MIPMAP, 0xffff, // Mipmap mask - see autodocs
TAG_DONE);
if (!tex || error != W3D_SUCCESS) {
printf("Error generating light texture: ");
switch(error) {
case W3D_ILLEGALINPUT:
printf("Illegal input\n");
break;
case W3D_NOMEMORY:
printf("Out of memory\n");
break;
case W3D_UNSUPPORTEDTEXSIZE:
printf("Unsupported texture size\n");
break;
case W3D_NOPALETTE:
printf("Chunky texture without palette specified\n");
break;
case W3D_UNSUPPORTEDTEXFMT:
printf("Texture format not supported\n");
break;
default:
printf("ahem... An error has occured\n");
}
return FALSE;
}
return TRUE;
}
//-
//+ PrintInfo
void PrintInfo(W3D_Context* context)
{
int x,y;
static char buffer[256];
SetAPen(window->RPort, 2);
SetDrMd(window->RPort, JAM1);
x=450; y=100;
if (bufnum == 0) y += 480;
if (W3D_GetState(context, W3D_FAST) == W3D_ENABLED)
sprintf(buffer, "Fast mode");
else sprintf(buffer, " ");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
if (outline) sprintf(buffer, "Outline mode");
else sprintf(buffer, " ");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
if (aflag) sprintf(buffer, "Show MipMaps");
else sprintf(buffer, " ");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
if (bflag) sprintf(buffer, "Vertex coordinates");
else sprintf(buffer, " ");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
if (cflag) sprintf(buffer, "Slow motion");
else sprintf(buffer, " ");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
if (W3D_GetState(context, W3D_PERSPECTIVE) == W3D_ENABLED)
sprintf(buffer, "Perspective");
else
sprintf(buffer, "Linear");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
if (W3D_GetState(context,W3D_TEXMAPPING) == W3D_ENABLED)
sprintf(buffer, "Texture Mapping");
else
sprintf(buffer, "Gouraud Shading");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
switch(CurrentBlend) {
case 0:
sprintf(buffer, "Blend REPLACE");
break;
case 1:
sprintf(buffer, "Blend DECAL");
break;
case 2:
sprintf(buffer, "Blend MODULATE");
break;
case 3:
sprintf(buffer, "Blend BLEND");
break;
default:
sprintf(buffer, "Blend UNKNOWN");
}
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
sprintf(buffer, "theta=%3.1f", theta);
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
sprintf(buffer, "pos=(%3.1f %3.1f %3.1f)", Pos.x, Pos.y, Pos.z);
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
sprintf(buffer, "Z-Clipping Plane %3.2f", zdepth);
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
{
char *zm;
switch(zmode) {
case 0: zm = "Z-Buffer disabled"; break;
case W3D_Z_NEVER: zm = "Z-Buffer never pass"; break;
case W3D_Z_LESS: zm = "Z-Buffer less"; break;
case W3D_Z_GEQUAL: zm = "Z-Buffer greater/equal"; break;
case W3D_Z_LEQUAL: zm = "Z-Buffer less/equal"; break;
case W3D_Z_GREATER: zm = "Z-Buffer greater"; break;
case W3D_Z_NOTEQUAL:zm = "Z-Buffer not equal"; break;
case W3D_Z_EQUAL: zm = "Z-Buffer equal"; break;
case W3D_Z_ALWAYS: zm = "Z-Buffer always pass";break;
default: zm = "??? Unknown Z-Mode"; break;
}
Move(window->RPort, x,y); Text(window->RPort, zm, strlen(zm)); y+=14;
}
sprintf(buffer, "Last Z: %3.2f", LastZ);
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
if (W3D_GetState(context,W3D_BLENDING) == W3D_ENABLED)
sprintf(buffer, "Alpha Blending");
else
sprintf(buffer, "No Blending");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
switch (CurrentFog) {
case 0: sprintf(buffer, "Fog off"); break;
case 1: sprintf(buffer, "Fog linear"); break;
case 2: sprintf(buffer, "Fog exponential"); break;
case 3: sprintf(buffer, "Fog exponential 2"); break;
case 4: sprintf(buffer, "Fog interpolated"); break;
}
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
sprintf(buffer, "(%3.2f - %3.2f)",
context->fog.fog_start, context->fog.fog_end);
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
switch(curfilt) {
case 1: sprintf(buffer, "W3D_NEAREST"); break;
case 2: sprintf(buffer, "W3D_LINEAR"); break;
case 3: sprintf(buffer, "W3D_NEAREST_MIP_NEAREST"); break;
case 4: sprintf(buffer, "W3D_LINEAR_MIP_LINEAR"); break;
}
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
y=430; if (bufnum == 0) y+=480;
x=10;
sprintf(buffer, "A - Mipmap view B - Vertex coords C - Slow Motion P - Perspective Mapping");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
sprintf(buffer, "T - Texture Mapping F - Fogging L - Alpha 1..4 - Filter");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
sprintf(buffer, "E - Blendmode ESC - Quit");
Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
}
//-
//+ ClearWindow
void ClearWindow(W3D_Context *context,struct Window *window)
{
/*
This clears the window using a plain simple rectfill.
Note that it does many things with the texture handle,
which is not really illegal as long as you don't write
directly to the texture handle...
*/
UWORD *t = tex->texdest;
int i,j,k;
int w = tex->texwidth;
int h = tex->texheight;
EraseRect(window->RPort, 0, (1-bufnum) * 480, 639, (1-bufnum) * 480 + 479);
if (dflag) {
int blah = (1-bufnum)*480;
SetAPen(window->RPort,10);
for (i=30; i<480; i+=30) {
Move(window->RPort, 0, i+blah);
Draw(window->RPort, 639, i+blah);
}
for (i=30; i<640; i+=30) {
Move(window->RPort, i, blah);
Draw(window->RPort, i, blah+479);
}
}
if (aflag) {
// If AFlag is set, draw the mipmap
WritePixelArray(tex->texsource, 0,0, w*4,
window->RPort, 0,(1-bufnum)*480, w,h, RECTFMT_ARGB);
if (w>h) {
j = w/2;
k = w;
} else{
j = h/2;
k = w;
}
i=0;
while (j) {
WritePixelArray(tex->mipmaps[i++],0,0,w*2,
window->RPort,
k,(1-bufnum)*480, w/2,h/2, RECTFMT_ARGB);
k+=w/2;
j/=2;
w/=2; if (w == 0) w = 1;
h/=2; if (h == 0) h = 1;
}
}
PrintInfo(context);
}
//-
//+ DrawWall
void DrawWall(W3D_Context *context)
{
static char buffer[512];
int i;
Transform(Pos, theta); // Do the perspective transformations
tri.tex = tex; // Set the texture handle
/*
A few notes about the triangle structure:
The "x" and "y" components are pretty obvious. They specify the screen
coordinates of the corresponding vertex (as a float; this gives you
sub-pixel accuracy, which is especially useful for small triangles).
The "z" component is the depth of the vertex. 0.0 means this vertex
sticks to the glass of your monitor (i.e. is closest to the front
clipping plane), while 1.0 means that the vertex is far away. The "z"
component is used for Z-Buffering, and, depending on the driver, might
be used for fogging as well
"u" and "v" are the texture coordinates on this vertex, expressed
as pixels on the map. Note that this conforms with the OpenGL notion
of "u" and "v". "u" and "v" are not to be confused with OpenGL's
"s" and "t", which are in the range [0..1].
color is the vertex color if lighting is used. Note that the alpha
value might or might not be used, depending on the blending mode.
The ViRGE implementation ignores this value, since the vertex alpha
is required for fogging.
Note however, that the texture alpha is always taken into account (if
the required blending mode is selected)
*/
tri.v1.x = TempSquare[3].x; tri.v1.y = TempSquare[3].y; tri.v1.z = TempSquare[3].z;
tri.v1.w = TempSquare[3].iz; //1.f-tri.v1.z;
tri.v1.u = Square[3].u; tri.v1.v = Square[3].v;
tri.v1.color.r = 1.0; tri.v1.color.g = 1.0; tri.v1.color.b = 1.0; tri.v1.color.a = 1.0;
tri.v2.x = TempSquare[1].x; tri.v2.y = TempSquare[1].y; tri.v2.z = TempSquare[1].z;
tri.v2.w = TempSquare[1].iz; //1.f-tri.v2.z;
tri.v2.u = Square[1].u; tri.v2.v = Square[1].v;
tri.v2.color.r = 1.0; tri.v2.color.g = 0.0; tri.v2.color.b = 0.0; tri.v2.color.a = 0.5;
tri.v3.x = TempSquare[0].x; tri.v3.y = TempSquare[0].y; tri.v3.z = TempSquare[0].z;
tri.v3.w = TempSquare[0].iz; //1.f-tri.v3.z;
tri.v3.u = Square[0].u; tri.v3.v = Square[0].v;
tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 0.1; tri.v3.color.a = 1.0;
// You must lock the hardware prior to drawing anything.
// Note that AUTOLOCKING, if enabled, will do this for you,
// but it is strictly recommended that you do locking yourself,
// since performance will suffer if you lock the hardware for
// every triangle. It is more efficient to lock hardware once for
// a few triangles, for example, for one polygon.
//
// NOTE 2: The CyberGfx implementation of the graphic sub-system
// driver uses LockBitmap() for this, so you may not hold the
// lock longer than one display frame (i.e. for a short time)
if (W3D_SUCCESS != W3D_LockHardware(context)) {
// printf("Error: Can`t lock hardware\n");
return;
}
// Go ahead and fire off the first triangle.
W3D_DrawTriangle(context, &tri);
// Fill in the triangle structure again.
tri.v1.x = TempSquare[1].x; tri.v1.y = TempSquare[1].y; tri.v1.z = TempSquare[1].z;
tri.v1.w = TempSquare[1].iz; //1.f-tri.v1.z;
tri.v1.u = Square[1].u; tri.v1.v = Square[1].v;
tri.v2.x = TempSquare[2].x; tri.v2.y = TempSquare[2].y; tri.v2.z = TempSquare[2].z;
tri.v2.w = TempSquare[2].iz; //1.f-tri.v2.z;
tri.v2.u = Square[2].u; tri.v2.v = Square[2].v;
tri.v3.x = TempSquare[3].x; tri.v3.y = TempSquare[3].y; tri.v3.z = TempSquare[3].z;
tri.v3.w = TempSquare[3].iz; //1.f-tri.v3.z;
tri.v3.u = Square[3].u; tri.v3.v = Square[3].v;
tri.v1.color.r = 1.0; tri.v1.color.g = 0.0; tri.v1.color.b = 0.0; tri.v1.color.a = 0.5;
tri.v2.color.r = 0.0; tri.v2.color.g = 0.0; tri.v2.color.b = 1.0; tri.v2.color.a = 0.1;
tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 1.0; tri.v3.color.a = 1.0;
// Fire off the second triangle. Note that the drawing routines
// will wait before writing the values to the registers, but
// if the W3D_SYNCHRON state is not set, it will return immediately
// and not wait for completion of the operation. In this case
// it is your duty to wait until the hardware is idle again.
W3D_DrawTriangle(context, &tri);
if (result[3]) {
ULONG Blend;
W3D_SetBlendMode(context, W3D_SRC_ALPHA, W3D_ONE_MINUS_SRC_ALPHA);
Blend = W3D_GetState(context, W3D_BLENDING);
W3D_SetState(context, W3D_BLENDING, W3D_ENABLE);
tri.tex = lighttex; // Set the texture handle
tri.v1.x = TempSquare[3].x; tri.v1.y = TempSquare[3].y; tri.v1.z = TempSquare[3].z;
tri.v1.w = TempSquare[3].iz; //1.f-tri.v1.z;
tri.v1.u = LSquare[3].u; tri.v1.v = LSquare[3].v;
tri.v1.color.r = 1.0; tri.v1.color.g = 1.0; tri.v1.color.b = 1.0; tri.v1.color.a = 1.0;
tri.v2.x = TempSquare[1].x; tri.v2.y = TempSquare[1].y; tri.v2.z = TempSquare[1].z;
tri.v2.w = TempSquare[1].iz; //1.f-tri.v2.z;
tri.v2.u = LSquare[1].u; tri.v2.v = LSquare[1].v;
tri.v2.color.r = 1.0; tri.v2.color.g = 1.0; tri.v2.color.b = 1.0; tri.v2.color.a = 1.0;
tri.v3.x = TempSquare[0].x; tri.v3.y = TempSquare[0].y; tri.v3.z = TempSquare[0].z;
tri.v3.w = TempSquare[0].iz; //1.f-tri.v3.z;
tri.v3.u = LSquare[0].u; tri.v3.v = LSquare[0].v;
tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 1.0; tri.v3.color.a = 1.0;
W3D_DrawTriangle(context, &tri);
tri.v1.x = TempSquare[1].x; tri.v1.y = TempSquare[1].y; tri.v1.z = TempSquare[1].z;
tri.v1.w = TempSquare[1].iz; //1.f-tri.v1.z;
tri.v1.u = LSquare[1].u; tri.v1.v = LSquare[1].v;
tri.v2.x = TempSquare[2].x; tri.v2.y = TempSquare[2].y; tri.v2.z = TempSquare[2].z;
tri.v2.w = TempSquare[2].iz; //1.f-tri.v2.z;
tri.v2.u = LSquare[2].u; tri.v2.v = LSquare[2].v;
tri.v3.x = TempSquare[3].x; tri.v3.y = TempSquare[3].y; tri.v3.z = TempSquare[3].z;
tri.v3.w = TempSquare[3].iz; //1.f-tri.v3.z;
tri.v3.u = LSquare[3].u; tri.v3.v = LSquare[3].v;
tri.v1.color.r = 1.0; tri.v1.color.g = 1.0; tri.v1.color.b = 1.0; tri.v1.color.a = 1.0;
tri.v2.color.r = 1.0; tri.v2.color.g = 1.0; tri.v2.color.b = 1.0; tri.v2.color.a = 1.0;
tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 1.0; tri.v3.color.a = 1.0;
W3D_DrawTriangle(context, &tri);
W3D_SetState(context, W3D_BLENDING, Blend);
}
if (outline) {
static W3D_Color col[4] = {
{0.9, 0.9, 0.0, 1.0},
{0.9, 0.0, 0.1, 0.2},
{0.0, 0.0, 0.9, 0.5},
{0.9, 0.9, 0.9, 1.0}
};
static W3D_Lines temp;
static W3D_Vertex v[4];
for(i = 0; i < 4; i++) {
v[i].x = TempSquare[i].x;
v[i].y = TempSquare[i].y;
v[i].z = TempSquare[i].z; // Needed for zbuffer
v[i].w = TempSquare[i].iz; // Needed for fogging
v[i].color.r = col[i].r;
v[i].color.g = col[i].g;
v[i].color.b = col[i].b;
v[i].color.a = col[i].a;
}
temp.v = v;
temp.vertexcount = 4;
W3D_DrawLineLoop(context, &temp);
}
if (second_wall) {
float t2;
t2 = 360.0 - theta;
if (t2 < 0) t2 = 360.0 - t2;
Transform(Pos, t2); // Do the perspective transformations
tri.tex = tex; // Set the texture handle
tri.v1.x = TempSquare[3].x; tri.v1.y = TempSquare[3].y; tri.v1.z = TempSquare[3].z;
tri.v1.w = TempSquare[3].iz; //1.f-tri.v1.z;
tri.v1.u = Square[3].u; tri.v1.v = Square[3].v;
tri.v1.color.r = 1.0; tri.v1.color.g = 1.0; tri.v1.color.b = 1.0; tri.v1.color.a = 1.0;
tri.v2.x = TempSquare[1].x; tri.v2.y = TempSquare[1].y; tri.v2.z = TempSquare[1].z;
tri.v2.w = TempSquare[1].iz; //1.f-tri.v2.z;
tri.v2.u = Square[1].u; tri.v2.v = Square[1].v;
tri.v2.color.r = 1.0; tri.v2.color.g = 0.0; tri.v2.color.b = 0.0; tri.v2.color.a = 1.0;
tri.v3.x = TempSquare[0].x; tri.v3.y = TempSquare[0].y; tri.v3.z = TempSquare[0].z;
tri.v3.w = TempSquare[0].iz; //1.f-tri.v3.z;
tri.v3.u = Square[0].u; tri.v3.v = Square[0].v;
tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 0.0; tri.v3.color.a = 1.0;
// Go ahead and fire off the first triangle.
W3D_DrawTriangle(context, &tri);
// Fill in the triangle structure again.
tri.v1.x = TempSquare[1].x; tri.v1.y = TempSquare[1].y; tri.v1.z = TempSquare[1].z;
tri.v1.w = TempSquare[1].iz; //1.f-tri.v1.z;
tri.v1.u = Square[1].u; tri.v1.v = Square[1].v;
tri.v2.x = TempSquare[2].x; tri.v2.y = TempSquare[2].y; tri.v2.z = TempSquare[2].z;
tri.v2.w = TempSquare[2].iz; //1.f-tri.v2.z;
tri.v2.u = Square[2].u; tri.v2.v = Square[2].v;
tri.v3.x = TempSquare[3].x; tri.v3.y = TempSquare[3].y; tri.v3.z = TempSquare[3].z;
tri.v3.w = TempSquare[3].iz; //1.f-tri.v3.z;
tri.v3.u = Square[3].u; tri.v3.v = Square[3].v;
tri.v1.color.r = 1.0; tri.v1.color.g = 0.0; tri.v1.color.b = 0.0; tri.v1.color.a = 1.0;
tri.v2.color.r = 0.0; tri.v2.color.g = 0.0; tri.v2.color.b = 1.0; tri.v2.color.a = 1.0;
tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 1.0; tri.v3.color.a = 1.0;
// Fire off the second triangle. Note that the drawing routines
// will wait before writing the values to the registers, but
// if the W3D_SYNCHRON state is not set, it will return immediately
// and not wait for completion of the operation. In this case
// it is your duty to wait until the hardware is idle again.
W3D_DrawTriangle(context, &tri);
if (outline) {
W3D_Color col[4] = {
{0.9, 0.9, 0.0, 1.0},
{0.9, 0.0, 0.0, 1.0},
{0.0, 0.0, 0.9, 1.0},
{0.9, 0.9, 0.9, 1.0}
};
W3D_Line temp;
temp.v1.color.a = 1.0;
temp.v2.color.a = 0.2;
for(i = 0; i < 4; i++) {
temp.v1.x = TempSquare[i].x;
temp.v1.y = TempSquare[i].y;
temp.v1.z = TempSquare[i].z; // Needed for zbuffer
temp.v1.w = TempSquare[i].iz; // Needed for fogging
temp.v2.x = TempSquare[(i+1)%4].x;
temp.v2.y = TempSquare[(i+1)%4].y;
temp.v2.z = TempSquare[(i+1)%4].z;
temp.v2.w = TempSquare[(i+1)%4].iz;
temp.v1.color.r = col[i].r;
temp.v1.color.g = col[i].g;
temp.v1.color.b = col[i].b;
temp.v2.color.r = col[(i+1)%4].r;
temp.v2.color.g = col[(i+1)%4].g;
temp.v2.color.b = col[(i+1)%4].b;
W3D_DrawLine(context, &temp);
}
}
}
W3D_UnLockHardware(context);
SetAPen(window->RPort, 249);
RectFill(window->RPort, 638,0,639,1);
// If the user flipped the bflag on, draw the coordinates at the
// polygon vertices
if (bflag) {
SetAPen(window->RPort, 255);
for (i=0; i<4; i++) {
#ifndef __STORM__
Move(window->RPort,(long)TempSquare[i].x, (long)TempSquare[i].y+(1-bufnum)*480);
sprintf(buffer, "%3.2f,%3.2f", TempSquare[i].z, TempSquare[i].iz);
Text(window->RPort, buffer, strlen(buffer));
#else /* compiler bug workaround */
float temp, temp2;
temp = TempSquare[i].iz;
temp2 = TempSquare[i].z;
Move(window->RPort,(long)TempSquare[i].x, (long)TempSquare[i].y+(1-bufnum)*480);
sprintf(buffer, "%3.2f,%3.2f", temp2, temp);
Text(window->RPort, buffer, strlen(buffer));
#endif
}
}
}
//-
//+ dummy
void dummy(void)
{
volatile int dont_optimize_me_away;
return;
}
//-
//+ SwitchBuffer
void SwitchBuffer(W3D_Context *context, struct BitMap *bm, struct Screen *scr, BOOL clip)
{
W3D_Scissor s = {0, 0, 640, 480};
struct ViewPort *vp = &(scr->ViewPort);
if (clip) {
s.left = 10;
s.top = 20;
s.width = 400;
s.height = 300;
}
if (bufnum == 0) {
W3D_SetDrawRegion(context, bm, 0, &s);
vp->RasInfo->RyOffset = 480;
ScrollVPort(vp);
WaitBOVP(vp);
bufnum = 1-bufnum;
if (clip) W3D_SetScissor(context, &s);
} else {
W3D_SetDrawRegion(context, bm, 480, &s);
vp->RasInfo->RyOffset = 0;
ScrollVPort(vp);
WaitBOVP(vp);
bufnum = 1-bufnum;
if (clip) W3D_SetScissor(context, &s);
}
}
//-
//+ PrintDriverInfo
void PrintDriverInfo(void)
{
ULONG res;
W3D_Driver **drivers = W3D_GetDrivers();
if (*drivers == NULL) {
printf("Panic: No Drivers found\n");
return;
}
printf("Available drivers:\n");
while (*drivers) {
printf("%s\n\tSupports format 0x%lX\n\t",
drivers[0]->name, drivers[0]->formats);
if (drivers[0]->swdriver) printf("CPU Driver\n");
else printf("Hardware Driver\n");
printf("\tPrimitives supported:\n\t");
res = W3D_QueryDriver(drivers[0], W3D_Q_DRAW_POINT, W3D_FMT_R5G5B5);
if (res != W3D_NOT_SUPPORTED) printf("[POINT] ");
res = W3D_QueryDriver(drivers[0], W3D_Q_DRAW_LINE, W3D_FMT_R5G5B5);
if (res != W3D_NOT_SUPPORTED) printf("[LINE] ");
res = W3D_QueryDriver(drivers[0], W3D_Q_DRAW_TRIANGLE, W3D_FMT_R5G5B5);
if (res != W3D_NOT_SUPPORTED) printf("[TRIANGLE] ");
printf("\n\tFiltering:\n\t");
res = W3D_QueryDriver(drivers[0], W3D_Q_BILINEARFILTER, W3D_FMT_R5G5B5);
if (res != W3D_NOT_SUPPORTED) printf("[BI-FILTER] ");
res = W3D_QueryDriver(drivers[0], W3D_Q_MMFILTER, W3D_FMT_R5G5B5);
if (res != W3D_NOT_SUPPORTED) printf("[MM-FILTER] ");
printf("\n");
drivers++;
}
printf("\n\n");
}
//-
//+ main
void main(int argc, char **argv)
{
ULONG ModeID, ID, format;
ULONG OpenErr, CError, res, ret;
struct BitMap *bm = NULL;
W3D_Context *context = NULL;
BOOL running=TRUE, clip = FALSE;
struct IntuiMessage *imsg;
int i,j,k;
ULONG flags;
int update;
float f;
UBYTE *newm;
UBYTE *hit = 0;
int si;
LONG repeat;
W3D_Scissor s = {0, 0, 640, 480};
W3D_Scissor sc = {32, 32, 64, 64};
rda = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL);
bzero(result, 40);
if (rda) {
rda->RDA_Source.CS_Buffer = NULL;
ReadArgs(TEMPLATE, result, rda);
FreeDosObject(DOS_RDARGS, rda);
}
if (result[2]) repeat = *((LONG *)result[2]);
else repeat = 1;
// Initialize the required libraries
CyberGfxBase = OpenLibrary("cybergraphics.library", 0L);
if (!CyberGfxBase) {
printf("Error opening CyberGraphX library\n");
goto panic;
}
#ifndef __PPC__
Warp3DBase = OpenLibrary("Warp3D.library", 2L);
if (!Warp3DBase) {
printf("Error opening Warp3D library\n");
goto panic;
#else
Warp3DPPCBase = OpenLibrary("Warp3DPPC.library", 2L);
if (!Warp3DPPCBase) {
printf("Error opening Warp3DPPC.library\n");
#endif
}
// Check for availability of drivers
flags = W3D_CheckDriver();
if (flags & W3D_DRIVER_3DHW) printf("Hardware driver available\n");
if (flags & W3D_DRIVER_CPU) printf("Software driver available\n");
if (flags & W3D_DRIVER_UNAVAILABLE) {
printf("PANIC: no driver available!!!\n");
goto panic;
}
PrintDriverInfo();
// Get a screen mode
// Due to the current limitations of the virge, this
// Screen must be 15 bit deep (NOT 16!)
#if 0
ModeID = BestCModeIDTags(
CYBRBIDTG_Depth, 15L,
CYBRBIDTG_NominalWidth, 640,
CYBRBIDTG_NominalHeight, 480,
CYBRBIDTG_BoardName, "CVision3D",
TAG_DONE);
#else
/*
** New in V2: The Screenmode requester
** This requester will ask for any screenmode the installed
** Hardware driver can handle, and also restrict the presented
** screen modes to 640x480 Modes...
*/
ModeID = W3D_RequestModeTags(
W3D_SMR_TYPE, W3D_DRIVER_3DHW,
W3D_SMR_SIZEFILTER, TRUE,
W3D_SMR_DESTFMT, ~W3D_FMT_CLUT,
ASLSM_MinWidth, 640,
ASLSM_MaxWidth, 641,
ASLSM_MinHeight, 480,
ASLSM_MaxHeight, 481,
TAG_DONE);
#endif
if (ModeID == INVALID_ID) {
printf("Error: No ModeID found\n");
goto panic;
}
// Open Screen
screen = OpenScreenTags(NULL,
SA_Height, 960,
SA_DisplayID, ModeID,
SA_Depth, 8,
SA_ErrorCode, &OpenErr,
SA_ShowTitle, FALSE,
SA_Draggable, FALSE,
TAG_DONE);
if (!screen) {
printf("Unable to open screen. Reason: Error code %d\n", OpenErr);
goto panic;
}
// Open window
// While this is not strictly nessessary, we use it because
// we want to get IDCMP messages. You can also use the screen's
// bitmap to render
window = OpenWindowTags(NULL,
WA_CustomScreen, screen,
WA_Activate, TRUE,
WA_Width, screen->Width,
WA_Height, screen->Height,
WA_Left, 0,
WA_Top, 0,
WA_Title, NULL,
WA_CloseGadget, FALSE,
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_VANILLAKEY|IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE|IDCMP_DELTAMOVE,
WA_Flags, WFLG_REPORTMOUSE|WFLG_RMBTRAP,
TAG_DONE);
SetRGB32(&(screen->ViewPort), 0, 0x40ffffff, 0x40ffffff, 0x88ffffff);
SetRGB32(&(screen->ViewPort), 10, 0xffffffff, 0x0, 0x0);
if (!window) {
printf("Unable to open window.\n");
goto panic;
}
// We want to use this bitmap
bm = window->RPort->BitMap;
SetAPen(window->RPort, 249);
RectFill(window->RPort, 0, 0, 639, 959);
// Go ahead and create the context. We need a context for every drawing
// operation, so this is done quite early in the program.
// NOTE: Some functions, like W3D_Query, do work without a context.
// The W3D_Query function without a context can be used to determine
// what kind of display/texture format the chip driver prefers.
context = W3D_CreateContextTags(&CError,
W3D_CC_MODEID, ModeID, // Mandatory for non-pubscreen
W3D_CC_BITMAP, bm, // The bitmap we'll use
W3D_CC_YOFFSET, 0, // We don't do dbuffering
W3D_CC_DRIVERTYPE, W3D_DRIVER_BEST, // Let Warp3D decide
W3D_CC_DOUBLEHEIGHT,TRUE, // Double height screen
W3D_CC_FAST, TRUE, // Fast drawing
TAG_DONE);
if (!context || CError != W3D_SUCCESS) {
printf("Error creating context. Reason:");
switch(CError) {
case W3D_ILLEGALINPUT:
printf("Illegal input to CreateContext function\n");
break;
case W3D_NOMEMORY:
printf("Out of memory\n");
break;
case W3D_NODRIVER:
printf("No suitable driver found\n");
break;
case W3D_UNSUPPORTEDFMT:
printf("Supplied bitmap cannot be handled by Warp3D\n");
break;
case W3D_ILLEGALBITMAP:
printf("Supplied bitmap not properly initialized\n");
break;
default:
printf("An error has occured... gosh\n");
}
goto panic;
}
if (result[0]) {
if (FALSE == GenTexture(context, (char *)result[0], repeat)) {
printf("Error loading/generating texture\n");
goto panic;
}
} else {
if (FALSE == GenTexture(context, "wall.ppm", repeat)) {
printf("Error loading/generating default texture\n");
goto panic;
}
}
if (result[3]) {
if (FALSE == GenLightmap(context, (char *)result[3], repeat)) {
printf("Error loading/generating lightmap\n");
goto panic;
}
}
/* If you need to know the "success" of setting a state, you can
find out by examining the return value of W3D_SetState. This should
be done if your program depends heavily on this feature. If not, you
may safely ignore the result. For example, the W3D_DITHERING state
might not have a large impact on the performance of your engine, so
you might ignore the outcome. On the other hand, it might be a severe
problem if your driver does not support texture mapping.
Things like this can be verified with W3D_Query after the context was
created, or with W3D_QueryDriver if you didn't create a context yet.
*/
if ( W3D_SetState(context, W3D_SCISSOR, W3D_ENABLE) == W3D_UNSUPPORTEDSTATE) {
printf("Scissoring not supported. Proceeding with fingers crossed\n");
}
// Set dithering. This will look considerably better on 15 bit displays.
W3D_SetState(context, W3D_DITHERING, W3D_ENABLE);
// Set texture wrapping mode to on.
// Read the section about limitations of the Virge for this
W3D_SetWrapMode(context, tex, W3D_REPEAT, W3D_REPEAT, NULL);
// Set blending to CurrentBlend mode (defaults to no alpha blending)
W3D_SetTexEnv(context, tex, BlendModes[CurrentBlend], NULL);
// Set Fog parameters
W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
// Set Texture mapping
W3D_SetState(context, W3D_TEXMAPPING, W3D_ENABLE);
// Set Drawing region
W3D_SetDrawRegion(context, bm, 0, &s);
// Set current color
W3D_SetCurrentColor(context, &ccol);
if (result[1]) {
// Set ZBuffer modes
if (W3D_SUCCESS != W3D_AllocZBuffer(context)) {
printf("Error: Can`t create ZBuffer\nZBuffering will not be available\n");
} else {
zb = TRUE;
W3D_SetState(context, W3D_ZBUFFERUPDATE, W3D_ENABLE);
W3D_ClearZBuffer(context, &zdepth);
}
}
// Clear window, then draw our first wall.
ClearWindow(context, window);
DrawWall(context);
running=TRUE;
while (running) {
// WaitPort(window->UserPort);
while (imsg = (struct IntuiMessage *)GetMsg(window->UserPort)) {
if (imsg == NULL) break;
switch(imsg->Class) {
case IDCMP_MOUSEBUTTONS:
if (imsg->Code == SELECTDOWN) {
drag = 1;
}
if (imsg->Code == SELECTUP) {
drag = 0;
}
if (imsg->Code == MENUDOWN) {
push = 1;
}
if (imsg->Code == MENUUP) {
push = 0;
}
break;
case IDCMP_MOUSEMOVE:
if (drag) {
theta += (float)(imsg->MouseX);
if (theta < 0.0) theta += 360.f;
if (theta > 360.0) theta -= 360.f;
}
if (push) {
Pos.z += (float)(imsg->MouseY)/128.f;
if (Pos.z < Front+1.f) Pos.z = Front+1.f;
if (Pos.z > Back-1.f) Pos.z = Back-1.f;
}
update = 1;
break;
case IDCMP_CLOSEWINDOW:
running=FALSE;
break;
case IDCMP_RAWKEY:
update=1;
if (cflag == 0) {
switch(imsg->Code) {
case 0x4F:
theta -= 4.f;
if (theta < 0.0) theta += 360.f;
break;
case 0x4e:
theta += 4.f;
if (theta > 360.0) theta -= 360.f;
break;
case 0x4C:
Pos.z -= 1.f;
if (Pos.z < Front+1.f) Pos.z = Front+1.f;
break;
case 0x4D:
Pos.z += 1.f;
if (Pos.z > Back-1.f) Pos.z = Back-1.f;
break;
case 0x50:
W3D_SetWrapMode(context, tex, W3D_CLAMP, W3D_CLAMP, NULL);
break;
case 0x51:
W3D_SetWrapMode(context, tex, W3D_REPEAT, W3D_REPEAT, NULL);
break;
case 0x5f: // Debug key
clip = !clip;
break;
break;
}
} else {
switch(imsg->Code) {
case 0x4F:
theta -= 1.f;
if (theta < 0.0) theta += 360.f;
break;
case 0x4e:
theta += 1.f;
if (theta > 360.0) theta -= 360.f;
break;
case 0x4C:
Pos.z -= 0.25f;
if (Pos.z < Front+1.f) Pos.z = Front+1.f;
break;
case 0x4D:
Pos.z += 0.25f;
if (Pos.z > Back-1.f) Pos.z = Back-1.f;
break;
}
}
break;
case IDCMP_VANILLAKEY:
update = 1;
switch(imsg->Code) {
case '|':
newm = LoadTextureFromPPM((APTR)NULL, (char *)"smallugly.ppm", 30, &si, &si);
W3D_UpdateTexSubImage(context, tex, (void *)newm, 0, NULL, &sc, 0);
FreeVec(newm);
break;
case 'S':
second_wall = 1 - second_wall;
break;
case '8': // Move fog end further back
myFog.fog_end -= 0.01;
if (myFog.fog_end < 0.05) myFog.fog_end = 0.05;
W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
break;
case '5': // Move fog end forward
myFog.fog_end += 0.01;
if (myFog.fog_end+0.05 > myFog.fog_start) myFog.fog_end = myFog.fog_start-0.05;
W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
break;
case '9': // Move fog start further back
myFog.fog_start -= 0.01;
if (myFog.fog_start-0.05 < myFog.fog_end) myFog.fog_start = myFog.fog_end+0.05;
W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
break;
case '6': // Move fog start forward
myFog.fog_start += 0.01;
if (myFog.fog_start > 1.0) myFog.fog_start = 1.0;
W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
break;
case 'F': // Toggle fog quality
if (FogQuality == W3D_H_NICE) FogQuality = W3D_H_FAST;
else FogQuality = W3D_H_NICE;
W3D_Hint(context, W3D_H_FOGGING, FogQuality);
break;
case 't':
case 'T': // Toggle texture mapping
if (W3D_GetState(context, W3D_TEXMAPPING) == W3D_ENABLED)
W3D_SetState(context, W3D_TEXMAPPING, W3D_DISABLE);
else
W3D_SetState(context, W3D_TEXMAPPING, W3D_ENABLE);
break;
case 'p':
case 'P': // Toggle perspective mapping
if (forcelin == 1) break; // Exit if forced to linear
if (persp==0) persp=1;
else persp=0;
if (persp) W3D_SetState(context, W3D_PERSPECTIVE, W3D_ENABLE);
else W3D_SetState(context, W3D_PERSPECTIVE, W3D_DISABLE);
break;
case '1':
curfilt = 1;
ret = W3D_SetFilter(context, tex, W3D_NEAREST, W3D_NEAREST);
if (ret != W3D_SUCCESS) printf("Warning: Unsupported Filter mode\n");
if (lighttex) W3D_SetFilter(context, tex, W3D_NEAREST, W3D_NEAREST);
break;
case '2':
curfilt = 2;
ret = W3D_SetFilter(context, tex, W3D_LINEAR, W3D_LINEAR);
if (ret != W3D_SUCCESS) printf("Warning: Unsupported Filter mode\n");
if (lighttex) W3D_SetFilter(context, tex, W3D_LINEAR, W3D_LINEAR);
break;
case '3':
curfilt = 3;
ret = W3D_SetFilter(context, tex, W3D_NEAREST_MIP_NEAREST, W3D_NEAREST);
if (ret != W3D_SUCCESS) printf("Warning: Unsupported Filter mode\n");
if (lighttex) W3D_SetFilter(context, tex, W3D_NEAREST_MIP_NEAREST, W3D_NEAREST);
break;
case '4':
curfilt = 4;
ret = W3D_SetFilter(context, tex, W3D_LINEAR_MIP_LINEAR, W3D_LINEAR);
if (ret != W3D_SUCCESS) printf("Warning: Unsupported Filter mode\n");
if (lighttex) W3D_SetFilter(context, tex, W3D_LINEAR_MIP_LINEAR, W3D_LINEAR);
break;
case 'a':
case 'A': // Toggle "Show mipmaps" (A Flag)
#ifndef STORM // Something;s wrong with the cgx includes
aflag = 1-aflag;
#endif
break;
case 'b':
case 'B': // Toggle "Show coordinates" (B Flag)
bflag = 1-bflag;
break;
case 'c':
case 'C': // Toggle "Slowmotion" (C FLag)
cflag = 1-cflag;
break;
case 'd':
case 'D':
dflag = 1-dflag;
break;
case 'e':
case 'E': // Toggle Lighting
do {
CurrentBlend = (CurrentBlend+1)%4;
res = W3D_SetTexEnv(context, tex, BlendModes[CurrentBlend], NULL);
} while (res != W3D_SUCCESS);
break;
case 'f': // Toggle fog. Note we ignore success/failure
do {
CurrentFog = (CurrentFog+1)%5;
if (CurrentFog == 0) {
res = W3D_SetState(context, W3D_FOGGING, W3D_DISABLE);
} else {
res = W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
if (res == W3D_SUCCESS)
W3D_SetState(context, W3D_FOGGING, W3D_ENABLE);
}
} while (res != W3D_SUCCESS);
break;
case 'o':
case 'O':
outline = ~outline;
break;
case 'z':
case 'Z': // Toggle ZBuffer. Currently not supported
zmode++; if (zmode == 9) zmode=0;
if (zmode==0) {
W3D_SetState(context, W3D_ZBUFFER, W3D_DISABLE);
} else {
W3D_SetState(context, W3D_ZBUFFER, W3D_ENABLE);
if (W3D_DISABLED == W3D_GetState(context, W3D_ZBUFFER)) {
printf("Warning: Can`t enable ZBuffer\n");
}
W3D_SetZCompareMode(context, zmode);
}
break;
case 'L':
if (W3D_GetState(context, W3D_GOURAUD) == W3D_ENABLED)
W3D_SetState(context, W3D_GOURAUD, W3D_DISABLE);
else
W3D_SetState(context, W3D_GOURAUD, W3D_ENABLE);
break;
case 'l': // Toggle Alpha Blending
W3D_SetBlendMode(context, W3D_SRC_ALPHA, W3D_ONE_MINUS_SRC_ALPHA);
if (W3D_GetState(context, W3D_BLENDING) == W3D_ENABLED)
W3D_SetState(context, W3D_BLENDING, W3D_DISABLE);
else
W3D_SetState(context, W3D_BLENDING, W3D_ENABLE);
break;
case 's':
if (W3D_GetState(context, W3D_FAST) == W3D_ENABLED)
W3D_SetState(context, W3D_FAST, W3D_DISABLE);
else
W3D_SetState(context, W3D_FAST, W3D_ENABLE);
break;
case '+':
zdepth+=0.05;
if (zdepth>1.0) zdepth=1.0;
W3D_ClearZBuffer(context, &zdepth);
break;
case '-':
zdepth-=0.05;
if (zdepth<0.0) zdepth=0.0;
W3D_ClearZBuffer(context, &zdepth);
break;
case 27: // Esc or 'Q' quits
case 'Q':
running=FALSE;
break;
case 13:
{
W3D_Double test;
W3D_ReadZPixel(context, 10, 10, &test);
printf("Test: %g\n", (double)test);
}
break;
default:
break;
}
break;
}
if (imsg) {
ReplyMsg((struct Message *)imsg);
imsg = NULL;
}
}
SwitchBuffer(context, bm, screen, clip);
ClearWindow(context, window);
DrawWall(context);
if (zb && W3D_SUCCESS == W3D_LockHardware(context)) {
W3D_ClearZBuffer(context, &zdepth);
W3D_UnLockHardware(context);
}
}
panic:
printf("Closing down...\n");
if (context) W3D_FreeZBuffer(context);
if (tex) W3D_FreeTexObj(context, tex);
if (lighttex) W3D_FreeTexObj(context, lighttex);
if (context) W3D_DestroyContext(context);
if (texmap) FreeVec(texmap);
if (window) CloseWindow(window);
if (screen) CloseScreen(screen);
#ifndef __PPC__
if (Warp3DBase) CloseLibrary(Warp3DBase);
#else
if (Warp3DPPCBase) CloseLibrary(Warp3DPPCBase);
#endif
if (CyberGfxBase) CloseLibrary(CyberGfxBase);
exit(0);
}
//-